// Tencent is pleased to support the open source community by making ncnn available.
//
// Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

package com.tencent.yolov5ncnn;

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraManager;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import androidx.core.app.ActivityCompat;

import java.io.FileNotFoundException;
import java.io.IOException;
//
//import androidx.core.app.ActivityCompat;
//import androidx.core.content.ContextCompat;
//import android.support.v7.app.AppCompatActivity;

public class MainActivity extends Activity
{

    private static final String TAG = "MainActivity";
    private static final int SELECT_IMAGE = 1;
    private static final int CAM_IMAGE = 2;

    private static final String TestApp="TestApp";
    private static final int REQUEST_CAMERA_PERMISSION = 200;


    private ImageView imageView;
    private Bitmap bitmap = null;
    private Bitmap yourSelectedImage = null;

    private YoloV5Ncnn yolov5ncnn = new YoloV5Ncnn();

    private CameraManager mCameraManager = null;
    private Camera2Demo2 mCamera2Demo2 = null;
    private YoloV5Ncnn.Obj[] mObjects;

    private Bitmap mShow_img;


    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        boolean ret_init = yolov5ncnn.Init(getAssets());
        if (!ret_init)
        {
            Log.e("MainActivity", "yolov5ncnn Init failed");
        }

        imageView = (ImageView) findViewById(R.id.imageView);

        Button buttonImage = (Button) findViewById(R.id.buttonImage);// 选图
        buttonImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                Intent i = new Intent(Intent.ACTION_PICK);

                i.setType("image/*");
                startActivityForResult(i, SELECT_IMAGE); //起新界面，结束调用onActivityResult
            }
        });

        Button buttonDetect = (Button) findViewById(R.id.buttonDetect);//检测
        buttonDetect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if (yourSelectedImage == null)
                    return;

                YoloV5Ncnn.Obj[] objects = yolov5ncnn.Detect(yourSelectedImage, false);

                showObjects(objects);
            }
        });

        Button buttonDetectGPU = (Button) findViewById(R.id.buttonDetectGPU); //gpu检测
        buttonDetectGPU.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if (yourSelectedImage == null)
                    return;

                YoloV5Ncnn.Obj[] objects = yolov5ncnn.Detect(yourSelectedImage, true);

                showObjects(objects);
            }
        });

        Button buttonRealTimeDetect = (Button) findViewById(R.id.buttonRealTimeDetect); //实时检测
        buttonRealTimeDetect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {

                // 打开相机
                mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
                String cameraId = null;
                try {
                    cameraId = mCameraManager.getCameraIdList()[0]; // 默认使用第一个相机
                } catch (CameraAccessException e) {
                    Log.e("TAG", "Failed to access camera", e);
                }

                mCamera2Demo2 = new Camera2Demo2(mCameraManager, cameraId);
                // 开始背景线程
                mCamera2Demo2.startBackgroundThread();
                // 打开相机
                mCamera2Demo2.openCamera();

                // 创建一个新的线程并运行一个任务
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        // 这里的代码将在新线程中执行
                        Log.d(TAG, "Running in thread: " + Thread.currentThread().getName());

                        // 执行一些耗时的操作
                        performLongOperation();

                        // 更新 UI 需要在主线程中进行
//                        updateUI();
                    }
                }).start();



//                saveImageToGallery(mCamera2Demo2.mBytes); //
//                saveImageToGallery(mCamera2Demo2.mBitmap); //



            }
        });



//        // 检查相机权限是否已经被授予
//        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
//                != PackageManager.PERMISSION_GRANTED) {
//            // 如果没有获得权限，则请求权限
//            ActivityCompat.requestPermissions(this,
//                    new String[]{Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},
//                    REQUEST_CAMERA_PERMISSION);
//        } else {
//            // 如果权限已经被授予，则可以直接使用相机
//            // 例如，启动相机应用
////            startCamera();
//
//        }
        // 则请求权限
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},
                REQUEST_CAMERA_PERMISSION);
//        // 打开相机
//
//        mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
//
//        String cameraId = null;
//        try {
//            cameraId = mCameraManager.getCameraIdList()[0]; // 默认使用第一个相机
//        } catch (CameraAccessException e) {
//            Log.e("TAG", "Failed to access camera", e);
//        }

//        // 创建 Camera2Basic 实例
//        mCamera2Demo2 = new Camera2Demo2(mCameraManager, cameraId);
//        // 开始背景线程
//        mCamera2Demo2.startBackgroundThread();
//        // 打开相机
//        mCamera2Demo2.openCamera();




    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 关闭相机
        mCamera2Demo2.closeCamera();
    }



    private void performLongOperation() {
        int i = 0;
        while (i<500000){

            // 取相机图
            //pass
//                Intent it = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//                try {
//                    if (it.resolveActivity(getPackageManager()) != null) {
//                        startActivityForResult(it, CAM_IMAGE);
//                    }
//                } catch (ActivityNotFoundException e){
//                    System.out.println("Hello World!");
//                }

//                initializeCamera();
            i=i+1;

            Log.d(TestApp,"取相机图Log"+i);
            if (mCamera2Demo2.mBitmap == null){
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    continue;
                 }
                 continue;
            }
            bitmap = mCamera2Demo2.mBitmap.copy(Bitmap.Config.ARGB_8888, true);
            yourSelectedImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);

            // 检测
            mObjects = yolov5ncnn.Detect(yourSelectedImage, false);


            //画图
            mShow_img = getShowImg(mObjects);
//            showObjects(mObjects);
            updateUI();
//            try {
//                Thread.sleep(2000);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }

        }

    }



    private void updateUI() {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                // 更新 UI 的代码放在这里
                Log.d(TAG, "Updating UI in main thread");
//                showObjects(mObjects);
                imageView.setImageBitmap(mShow_img);
            }
        });
    }


    // 返回 show img
    private Bitmap getShowImg(YoloV5Ncnn.Obj[] objects)
    {
//        System.out.println("1111111123");
//        Log.d(TestApp,"HelloWorld");


        // draw objects on bitmap
        Bitmap rgba = bitmap.copy(Bitmap.Config.ARGB_8888, true);
        if (objects == null)
        {
            return rgba;
        }
        final int[] colors = new int[] {
                Color.rgb( 54,  67, 244),
                Color.rgb( 99,  30, 233),
                Color.rgb(176,  39, 156),
                Color.rgb(183,  58, 103),
                Color.rgb(181,  81,  63),
                Color.rgb(243, 150,  33),
                Color.rgb(244, 169,   3),
                Color.rgb(212, 188,   0),
                Color.rgb(136, 150,   0),
                Color.rgb( 80, 175,  76),
                Color.rgb( 74, 195, 139),
                Color.rgb( 57, 220, 205),
                Color.rgb( 59, 235, 255),
                Color.rgb(  7, 193, 255),
                Color.rgb(  0, 152, 255),
                Color.rgb( 34,  87, 255),
                Color.rgb( 72,  85, 121),
                Color.rgb(158, 158, 158),
                Color.rgb(139, 125,  96)
        };

        Canvas canvas = new Canvas(rgba);

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);

        Paint textbgpaint = new Paint();
        textbgpaint.setColor(Color.WHITE);
        textbgpaint.setStyle(Paint.Style.FILL);

        Paint textpaint = new Paint();
        textpaint.setColor(Color.BLACK);
        textpaint.setTextSize(26);
        textpaint.setTextAlign(Paint.Align.LEFT);

        for (int i = 0; i < objects.length; i++)
        {
            paint.setColor(colors[i % 19]);

            canvas.drawRect(objects[i].x, objects[i].y, objects[i].x + objects[i].w, objects[i].y + objects[i].h, paint);

            // draw filled text inside image
            {
                String text = objects[i].label + " = " + String.format("%.1f", objects[i].prob * 100) + "%";

                float text_width = textpaint.measureText(text);
                float text_height = - textpaint.ascent() + textpaint.descent();

                float x = objects[i].x;
                float y = objects[i].y - text_height;
                if (y < 0)
                    y = 0;
                if (x + text_width > rgba.getWidth())
                    x = rgba.getWidth() - text_width;

                canvas.drawRect(x, y, x + text_width, y + text_height, textbgpaint);

                canvas.drawText(text, x, y - textpaint.ascent(), textpaint);
            }
        }

//        imageView.setImageBitmap(rgba); //显示
        return rgba;
    }

    private void showObjects(YoloV5Ncnn.Obj[] objects)
    {
//        System.out.println("1111111123");
//        Log.d(TestApp,"HelloWorld");
        if (objects == null)
        {
            imageView.setImageBitmap(bitmap);
            return;
        }

        // draw objects on bitmap
        Bitmap rgba = bitmap.copy(Bitmap.Config.ARGB_8888, true);

        final int[] colors = new int[] {
            Color.rgb( 54,  67, 244),
            Color.rgb( 99,  30, 233),
            Color.rgb(176,  39, 156),
            Color.rgb(183,  58, 103),
            Color.rgb(181,  81,  63),
            Color.rgb(243, 150,  33),
            Color.rgb(244, 169,   3),
            Color.rgb(212, 188,   0),
            Color.rgb(136, 150,   0),
            Color.rgb( 80, 175,  76),
            Color.rgb( 74, 195, 139),
            Color.rgb( 57, 220, 205),
            Color.rgb( 59, 235, 255),
            Color.rgb(  7, 193, 255),
            Color.rgb(  0, 152, 255),
            Color.rgb( 34,  87, 255),
            Color.rgb( 72,  85, 121),
            Color.rgb(158, 158, 158),
            Color.rgb(139, 125,  96)
        };

        Canvas canvas = new Canvas(rgba);

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);

        Paint textbgpaint = new Paint();
        textbgpaint.setColor(Color.WHITE);
        textbgpaint.setStyle(Paint.Style.FILL);

        Paint textpaint = new Paint();
        textpaint.setColor(Color.BLACK);
        textpaint.setTextSize(26);
        textpaint.setTextAlign(Paint.Align.LEFT);

        for (int i = 0; i < objects.length; i++)
        {
            paint.setColor(colors[i % 19]);

            canvas.drawRect(objects[i].x, objects[i].y, objects[i].x + objects[i].w, objects[i].y + objects[i].h, paint);

            // draw filled text inside image
            {
                String text = objects[i].label + " = " + String.format("%.1f", objects[i].prob * 100) + "%";

                float text_width = textpaint.measureText(text);
                float text_height = - textpaint.ascent() + textpaint.descent();

                float x = objects[i].x;
                float y = objects[i].y - text_height;
                if (y < 0)
                    y = 0;
                if (x + text_width > rgba.getWidth())
                    x = rgba.getWidth() - text_width;

                canvas.drawRect(x, y, x + text_width, y + text_height, textbgpaint);

                canvas.drawText(text, x, y - textpaint.ascent(), textpaint);
            }
        }

        imageView.setImageBitmap(rgba); //显示
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK && null != data) {
            Uri selectedImage = data.getData(); //图片地址？

            try
            {
                if (requestCode == SELECT_IMAGE) {
                    bitmap = decodeUri(selectedImage); // uri to bitmap

                    yourSelectedImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);

                    imageView.setImageBitmap(bitmap); //显示图像
                }
                if (requestCode == CAM_IMAGE) {
//                    Bundle bundle = data.getExtras();
//                    Bitmap bitmap_cam = (Bitmap) bundle.get("data");

                    bitmap = decodeUri(selectedImage); // uri to bitmap
                    yourSelectedImage = bitmap.copy(Bitmap.Config.ARGB_8888, true);
                    imageView.setImageBitmap(bitmap); //显示图像
                }
            }
            catch (FileNotFoundException e)
            {
                Log.e("MainActivity", "FileNotFoundException");
                return;
            }
        }
    }

    private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException
    {
        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 640;

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
               || height_tmp / 2 < REQUIRED_SIZE) {
                break;
            }
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);

        // Rotate according to EXIF
        int rotate = 0;
        try
        {
            ExifInterface exif = new ExifInterface(getContentResolver().openInputStream(selectedImage));
            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotate = 270;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotate = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotate = 90;
                    break;
            }
        }
        catch (IOException e)
        {
            Log.e("MainActivity", "ExifInterface IOException");
        }

        Matrix matrix = new Matrix();
        matrix.postRotate(rotate);
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    }


    //保存图片到相册
//    private void saveImageToGallery(byte[] imageData) {
    private void saveImageToGallery(Bitmap bitmap1) {
        // 将字节数组转换为 Bitmap
//        Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
//        imageView.setImageBitmap(bitmap); //显示图像
        Bitmap bitmap2 = bitmap1.copy(Bitmap.Config.ARGB_8888, true);
        yourSelectedImage = bitmap2.copy(Bitmap.Config.ARGB_8888, true);
//        imageView.setImageBitmap(bitmap2);


//        // 创建一个文件名
////        String fileName = generateFileName();
//        String fileName = "image_" + System.currentTimeMillis() + ".jpg";
//
//        // 保存图片到相册
//        ContentValues values = new ContentValues();
//        values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
//        values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
//        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
//
//        Uri collection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
//        Uri imageUri = getContentResolver().insert(collection, values);
//
//        try (ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(imageUri, "w")) {
//            FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
//            bitmap1.compress(Bitmap.CompressFormat.JPEG, 100, fos); // 保存为 JPEG 格式
//            fos.close();
////            imageView.setImageURI(imageUri);
//            Log.d(TAG, "Image saved to gallery: " + imageUri);
//        } catch (IOException e) {
//            Log.e(TAG, "Error saving image to gallery", e);
//        }
    }




}
